package org.tib.concurrent;

import java.math.BigInteger;

/**
 * Implementing Fn = F(n-1) + F(n-2)
 * Where Fo = 0 and F1 = 1
 */
public class Fibonaci {
    // Computation definitions
    public final static Integer LOOP_FIBONACI = 1;
    public final static Integer RECURSION_FIBONACI = 2;

    /**
     * This is the loop implementation as denoted by Fibonaci.LOOP_FIBONACI.
     * @param sequence The sequence to compute the fibonaci figure.
     * @return The computed fibonaci figure.
     */
    public BigInteger computeFibonaci(int sequence) {
        BigInteger fib = BigInteger.valueOf(1);
        int i = 0;
        BigInteger curr = fib;
        BigInteger prev = fib.subtract(BigInteger.valueOf(1));
        while (i < sequence-1) {
            fib = curr.add(prev);
            prev = curr;
            curr = fib;
            i++;
        }
        return fib;
    }

    /**
     * This is the Recursion implementation (the expensive way) as denoted by Fibonaci.RECURSION_FIBONACI.
     * @param sequence The sequence to compute the fibonaci figure.
     * @return The computed fibonaci figure.
     */
    public BigInteger computeFibonaciRecursion(int sequence) {
        if (sequence <= 2) {
            return BigInteger.valueOf(1);
        }
        else {
            return computeFibonaciRecursion(sequence - 1).add(computeFibonaciRecursion(sequence  - 2));
        }
    }

    public static void main(String[] args) {
        Fibonaci fibs = new Fibonaci();
        System.out.println("The fibonaci number on computation : "+ fibs.computeFibonaci(5));
        System.out.println("The fibonaci number on recursion : "+ fibs.computeFibonaciRecursion(5));
    }
}
